using Commons.Models.Definitions;
using Commons.Models.Settings.Dtos;
using Commons.Models.Settings.Dtos.TradeValues;
using System;

namespace Commons.Models.Stats
{
	public class SimpleStat : IStat
	{
		private int _value;

		public virtual int Value
		{
			get
			{
				return _value + Delta;
			}
			protected set
			{
				_value = value;
			}
		}

		public virtual int Initial
		{
			get
			{
				return _value;
			}
		}

		public virtual int Delta { get; protected set; }

		public IStatDefinition Definition { get; protected set; }

		public Action<IStatUnit, int, int> StatChanged;

		public SimpleStat(SimpleStatDefinition definition)
			: this (definition, definition.Initial)
		{

		}

		public SimpleStat(IStatDefinition definition, int value)
		{
			this.Definition = definition;
			this.Value = value;
			this.Delta = 0;
		}

		public virtual void Add(int value)
		{
			if (value != 0)
			{
				if (CanAdd(value))
				{
					int previousValue = Value;

					Delta += value;

					if (StatChanged != null)
					{
						StatChanged(Definition.Unit, previousValue, Value);
					}
				}
				else
				{
					throw new ArgumentException("Cannot add " + value + " to " + Definition.Unit + " with current value " + Value);
				}
			}
		}

		public virtual void Substract(int value)
		{
			if (value != 0)
			{
				if (CanSubstract(value))
				{
					int previousValue = Value;

					Delta -= value;

					if (StatChanged != null)
					{
						StatChanged(Definition.Unit, previousValue, Value);
					}
				}
				else
				{
					throw new ArgumentException("Cannot substract " + value + " to " + Definition.Unit + " with current value " + Value);
				}
			}
		}

		public virtual bool CanAdd(int value)
		{
			return value < 0 ? CanSubstract(-value) : true;
		}

		public virtual bool CanSubstract(int value)
		{
			return value < 0 ? CanAdd(-value) : this.Value >= value;
		}

		public virtual void Apply()
		{
			_value += Delta;
			Delta = 0;
		}

		public virtual bool HasChanges()
		{
			return Delta != 0;
		}
	}
}
